package com.ydl.iec.demo;

import com.google.gson.Gson;
import com.google.gson.annotations.Expose;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;

import javax.swing.*;
import java.io.*;
import java.util.*;
import java.util.Timer;

@Data
@Slf4j
public class ResourceManage {
    public Map<String, Resource> resources = new HashMap<>(); //key properties文件名

    public Map<Integer, Point> allPoints = new HashMap<>();

    public int accepted = 0;
    /** 放电负数  充电正数 */
    public float[] planCurve = new float[288];


    public void init() {
        Gson gson = new Gson();
        InputStream resourceAsStream = Test.class.getClassLoader().getResourceAsStream("resource.json");
        try (BufferedReader br = new BufferedReader(new InputStreamReader(resourceAsStream))) {
            String json;
            StringBuilder sb = new StringBuilder();
            String line;
            while ((line = br.readLine()) != null) {
                sb.append(line);
            }
            json = sb.toString();
            ResourceManage resourceManage = gson.fromJson(json, ResourceManage.class);
            resources = resourceManage.resources;
            resources.forEach((key ,value)-> allPoints.putAll(value.getPoints()));
        } catch (IOException e) {
            log.error("resource.json"+"文件读取失败",e);
        }
    }

    public boolean splitPlanCurve() {
        //虚拟电厂所有资源最大可充功率和最大可放功率
        float totalMaxCharge = 0;
        float totalMaxDischarge = 0;
        for (Map.Entry<String, Resource> entry : resources.entrySet()) {
            Resource resource = entry.getValue();
            Map<Integer, Point> points = resource.getPoints();
            //资源不可用时跳过
            if(points.get(resource.getState()).getValue()==0)continue;
            totalMaxCharge += points.get(resource.getMaxCharge()).getValue();
            totalMaxDischarge += points.get(resource.getMaxDischarge()).getValue();
        }
        float maxCharge = getMaxCharge();
        float maxDischarge = getMaxDisCharge();
        //和计划曲线的最大可充放功率比较，超限报警
        if(maxCharge > totalMaxCharge || maxDischarge > totalMaxDischarge){
            log.error("总可充放功率超限，总充电功率="+maxCharge+",总放电功率"+maxDischarge);
            Test.slaveTest.getSysDataHandler().sendWarn();
            return false;
        }
        //分配到下游资源点，模拟数据
        for (Map.Entry<String, Resource> entry : resources.entrySet()) {
            Resource resource = entry.getValue();
            if(resource.getPoints().get(resource.getState()).getValue()==0)continue;
            resource.setPlan(planCurve, totalMaxCharge,totalMaxDischarge);
        }
        return true;
    }

    public Point getPoint(String resourceId,int pointId){
        return resources.get(resourceId).getPoints().get(pointId);
    }

    public float getMaxCharge(){
        float max = planCurve[0];
        for(float value : planCurve){
            if (value > max) {
                max = value;
            }
        }
        return max;
    }

    /**
     * 获取最大放电功率，负数取绝对值
     * @return
     */
    public float getMaxDisCharge(){
        float min = planCurve[0];
        for(float value : planCurve){
            if (value < min) {
                min = value;
            }
        }
        return Math.abs(min);
    }

    public void testPlanData(PlanTestData planTestData){
        log.info("模拟数据启动");
        this.planCurve = planTestData.getPlanCurve();
        splitPlanCurve();
        startProcess();
    }

    public void startProcess() {
        Test.timer.schedule(new TimerTask() {
            @Override
            public void run() {
                List<Point> sendPoints = new ArrayList<>();
                for (Map.Entry<String, Resource> stringResourceEntry : resources.entrySet()) {
                    //resource电站
                    Resource resource = stringResourceEntry.getValue();
                    //获取计划曲线数据
                    if(resource.getIndex()>=287){
                        log.info("计划已执行完毕");
                        Test.timer.cancel();
//                        Test.slaveTest.getSysDataHandler().sendYc(sendPoints);
                        return;
                    }
                    PlanCurveData planCurveData = resource.getPlanCurveDataList().get(resource.getIndex());
                    log.info(resource.getIndex()+":"+planCurveData.getTime());
//                    resource.setIndex(resource.getIndex()>=resource.getPlanCurveDataList().size()-1?0:resource.getIndex()+1);
                    Map<Integer, Point> points = resource.getPoints();
                    float currentPower = planCurveData.getPower() * resource.getRatio();
                    Point socPoint = resource.getPoints().get(resource.getSoc());
                    Point chargePoint = resource.getPoints().get(resource.getCharge());
                    Point dischargePoint = resource.getPoints().get(resource.getDischarge());
                    float energy = currentPower/12f; //充放电量，正数充电，负数放电
                    float charge = chargePoint.getValue() - energy;
                    float discharge = dischargePoint.getValue() + energy;
                    float soc = discharge/(charge+discharge)*100;
                    points.get(resource.getAp()).setValue(currentPower);
                    points.get(resource.getSoc()).setValue(soc);
                    points.get(resource.getCharge()).setValue(charge);
                    points.get(resource.getDischarge()).setValue(discharge);
                    ((JTextField)(Test.viewPanel.getComponents().get(resource.getAp()))).setText(String.valueOf(currentPower));
                    ((JTextField)(Test.viewPanel.getComponents().get(resource.getSoc()))).setText(String.valueOf(soc));
                    ((JTextField)(Test.viewPanel.getComponents().get(resource.getCharge()))).setText(String.valueOf(charge));
                    ((JTextField)(Test.viewPanel.getComponents().get(resource.getDischarge()))).setText(String.valueOf(discharge));
                    sendPoints.add(points.get(resource.getAp()));
                    sendPoints.add(socPoint);
                    sendPoints.add(chargePoint);
                    sendPoints.add(dischargePoint);
                    resource.setIndex(resource.getIndex()+1);
                }
                Test.slaveTest.getSysDataHandler().sendYc(sendPoints);
            }
        },1000,Test.updateInterval);
    }
}
